﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
#if !NET8_0_OR_GREATER
using DimensionsHelper.Common.Utils;
#endif

namespace DimensionsHelper.Common.Metadata.Script;

[AttributeUsage(AttributeTargets.Method)]
public class ExpressionBuiltInFunctionAttribute : Attribute
{
    public ExpressionBuiltInFunctionAttribute(int metadataContextParameterIndex = -1)
    {
        MetadataContextParameterIndex = metadataContextParameterIndex;
    }

    public int MetadataContextParameterIndex { get; }
}

/// <summary>
///     脚本支持的内建函数。
/// </summary>
public class ExpressionBuiltInFunctions
{
    private static readonly Dictionary<string, FunctionInfo> BuiltInFunctions = 
        new Dictionary<string, FunctionInfo>();
        
    static ExpressionBuiltInFunctions()
    {
        InitializeFunctions(typeof(ExpressionBuiltInFunctions));
    }


    public static string[] GetBuiltInFunctionNames()
    {
        return BuiltInFunctions.Keys.ToArray();
    }


    private static void InitializeFunctions(Type type)
    {
        foreach (MethodInfo item in type.GetMethods(BindingFlags.Static | BindingFlags.Public))
        {
            var attr = item.GetCustomAttribute<ExpressionBuiltInFunctionAttribute>();

            if (attr != null &&
                item.ReturnType.IsAssignableTo(typeof(ExpressionBasicType)))
            {
                BuiltInFunctions.TryAdd(item.Name.ToLower(),
                    new FunctionInfo(item, attr.MetadataContextParameterIndex));
            }
        }
    }

    /// <summary>
    ///     读取类型中使用<see cref="ExpressionBuiltInFunctionAttribute" />定义的内建函数，
    ///     必须是静态函数。并且参数和返回值都继承<see cref="ExpressionBasicType" />。
    /// </summary>
    /// <param name="type"></param>
    public static void Load(Type type)
    {
        InitializeFunctions(type);
    }

    /// <summary>
    ///     调用给定名称的内建函数并返回表达式基础类型值。
    /// </summary>
    /// <param name="functionName">函数名，不区分大小写</param>
    /// <param name="args">参数列表，此方法接收任意数量的参数。</param>
    /// <returns>函数调用的返回值</returns>
    public static ExpressionBasicType Invoke(string functionName, params ExpressionBasicType[] args)
    {
        if (!BuiltInFunctions.TryGetValue(functionName.ToLower(), out FunctionInfo info))
        {
            throw new Exception($"不受支持的函数：{functionName}。");
        }

        return info.Method.Invoke(null, [args]) as ExpressionBasicType ??
               throw new Exception($"函数{info.Method.Name}没有合适的返回值。");
    }


    /// <summary>
    ///     获取指定函数的固定元数据上下文参数索引。无固定的返回-1。
    /// </summary>
    /// <param name="functionName"></param>
    /// <returns></returns>
    public static int GetMetadataContextIndex(string functionName)
    {
        return BuiltInFunctions.TryGetValue(functionName.ToLower(), out FunctionInfo info) ? info.Context : -1;
    }


    private static void CheckArgumentNumbers(string functionName, int needArgsNumber, int maxArgsNumber,
        int givenArgsNumber)
    {
        if (givenArgsNumber < needArgsNumber)
        {
            throw new Exception($"传入的参数过少，函数{functionName}需要{needArgsNumber}个参数。");
        }

        if (maxArgsNumber > 0 && givenArgsNumber > maxArgsNumber)
        {
            throw new Exception($"传入的参数过多，函数{functionName}最多接收{maxArgsNumber}个参数。");
        }
    }

    private static object GetTypeValue(ExpressionBasicType value, BasicTypes type)
    {
        if (value.CanImplicitlyConvert(type))
        {
            return value.GetValue(type);
        }

        throw ThrowHelper.TypeConvertFailed(value.Type.ToString(), type.ToString());
    }


    private readonly struct FunctionInfo
    {
        public readonly int Context;
        public readonly MethodInfo Method;

        public FunctionInfo(MethodInfo method, int context)
        {
            Context = context;
            Method = method;
        }
    }

    #region Categorical Functions

    /// <summary>
    ///     计算分类值内类别数量的内建函数。
    /// </summary>
    /// <param name="values">给定值，会转换成Categorical类型。</param>
    /// <returns>分类值中的元素个数, 返回类型是<see cref="ExpressionInteger" /></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType AnswerCount(params ExpressionBasicType[] values)
    {
        CheckArgumentNumbers(nameof(AnswerCount), 1, 1, values.Length);
        return new ExpressionInteger(((Categorical)GetTypeValue(values[0], BasicTypes.Categorical)).Count);
    }


    /// <summary>
    ///     计算分类值是否包含给定分类值的所有元素
    /// </summary>
    /// <param name="vals"></param>
    /// <returns>返回类型是<see cref="ExpressionBoolean" /></returns>
    [ExpressionBuiltInFunction(0)]
    public static ExpressionBasicType ContainsAll(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(ContainsAll), 2, 3, vals.Length);

        Categorical _1Arg = (Categorical)GetTypeValue(vals[0], BasicTypes.Categorical);
        Categorical _2Arg = (Categorical)GetTypeValue(vals[1], BasicTypes.Categorical);

        bool exactly = false;
        if (vals.Length == 3)
        {
            exactly = (bool)GetTypeValue(vals[2], BasicTypes.Boolean);
        }

        return new ExpressionBoolean(_1Arg.ContainsAll(_2Arg, exactly));
    }


    /// <summary>
    ///     计算分类值是否包含给定分类值的任意一个元素
    /// </summary>
    /// <param name="vals"></param>
    /// <returns>返回类型是<see cref="ExpressionBoolean" /></returns>
    [ExpressionBuiltInFunction(0)]
    public static ExpressionBasicType ContainsAny(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(ContainsAny), 2, 3, vals.Length);

        Categorical _1Arg = (Categorical)GetTypeValue(vals[0], BasicTypes.Categorical);
        Categorical _2Arg = (Categorical)GetTypeValue(vals[1], BasicTypes.Categorical);

        bool exactly = false;
        if (vals.Length == 3)
        {
            exactly = (bool)GetTypeValue(vals[2], BasicTypes.Boolean);
        }

        return new ExpressionBoolean(_1Arg.Contains(_2Arg, exactly));
    }

    /// <summary>
    ///     判断给定分类值是否和另一个分类值由指定数量的交集元素。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns>返回类型是<see cref="ExpressionBoolean" /></returns>
    [ExpressionBuiltInFunction(0)]
    public static ExpressionBasicType ContainsSome(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(ContainsSome), 2, 5, vals.Length);

        Categorical _1Arg = (Categorical)GetTypeValue(vals[0], BasicTypes.Categorical);
        Categorical _2Arg = (Categorical)GetTypeValue(vals[1], BasicTypes.Categorical);

        int min = 1;
        if (vals.Length >= 3)
        {
            min = (int)GetTypeValue(vals[2], BasicTypes.Integer);
        }

        int max = _2Arg.Count;
        if (vals.Length >= 4)
        {
            max = (int)GetTypeValue(vals[3], BasicTypes.Integer);
        }

        bool exactly = false;
        if (vals.Length >= 5)
        {
            exactly = (bool)GetTypeValue(vals[4], BasicTypes.Boolean);
        }

        return new ExpressionBoolean(_1Arg.Contains(_2Arg, min, max, exactly));
    }


    /// <summary>
    ///     返回在第一个分类列表中不在第二个分类列表中的元素的分类列表。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns>返回类型是<see cref="Categorical" /></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Difference(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Difference), 2, 2, vals.Length);
        Categorical _1Arg = (Categorical)GetTypeValue(vals[0], BasicTypes.Categorical);
        Categorical _2Arg = (Categorical)GetTypeValue(vals[1], BasicTypes.Categorical);
        return _1Arg.Difference(_2Arg);
    }


    /// <summary>
    ///     获取分类值指定位置的元素。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns>返回类型是<see cref="Categorical" /></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType GetAnswer(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(GetAnswer), 2, 2, vals.Length);
        Categorical _1Arg = (Categorical)GetTypeValue(vals[0], BasicTypes.Categorical);
        ExpressionInteger _2Arg = (ExpressionInteger)GetTypeValue(vals[1], BasicTypes.Integer);
        return new Categorical(_1Arg[_2Arg.Value]);
    }

    /// <summary>
    ///     计算多个集合的交集。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns>返回类型是<see cref="Categorical" /></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Intersection(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Intersection), 1, 0, vals.Length);
        Categorical res = (Categorical)GetTypeValue(vals[0], BasicTypes.Categorical);
        for (int i = 1; i < vals.Length; i++)
        {
            res = res.Intersection(vals[i]);
        }

        return res;
    }

    /// <summary>
    ///     去掉分类值中的重复值并返回一个新的分类值。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Unique(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Unique), 1, 1, vals.Length);
        Categorical cat = (Categorical)GetTypeValue(vals[0], BasicTypes.Categorical);
        return cat.Unique();
    }

    /// <summary>
    ///     计算多个集合的并集。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns>返回类型是<see cref="Categorical" /></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Union(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Union), 1, 0, vals.Length);
        Categorical res = (Categorical)GetTypeValue(vals[0], BasicTypes.Categorical);
        for (int i = 1; i < vals.Length; i++)
        {
            res = res.Union(vals[i]);
        }

        return res;
    }

    /// <summary>
    ///     计算多个集合的异或集。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns>返回类型是<see cref="Categorical" /></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType XUnion(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(XUnion), 1, 0, vals.Length);
        Categorical res = (Categorical)GetTypeValue(vals[0], BasicTypes.Categorical);
        for (int i = 1; i < vals.Length; i++)
        {
            res = res.XUnion(vals[i]);
        }

        return res;
    }


    /// <summary>
    ///     计算分类列表值的下限索引，默认返回0。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns>返回类型是<see cref="ExpressionInteger" /></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType LBound(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(LBound), 1, 2, vals.Length);
        return new ExpressionInteger(0);
    }

    /// <summary>
    ///     计算分类列表值的上限索引，空列表时返回0。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns>返回类型是<see cref="ExpressionInteger" /></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType UBound(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(UBound), 1, 2, vals.Length);
        Categorical _1Arg = (Categorical)GetTypeValue(vals[0], BasicTypes.Categorical);
        return new ExpressionInteger(_1Arg.Count == 0 ? 0 : _1Arg.Count - 1);
    }

    #endregion

    #region Text, Categorical, or Array Functions

    // Find(Val, Key [, Skip [, Reverse [, IgnoreCase]]])

    /// <summary>
    ///     查找指定值在分类列表中的索引。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Find(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Find), 2, 5, vals.Length);

        string _2Arg = (string)GetTypeValue(vals[1], BasicTypes.String);

        int skip = 0;
        if (vals.Length >= 3)
        {
            skip = (int)GetTypeValue(vals[2], BasicTypes.Integer);
        }

        bool rev = false;
        if (vals.Length >= 4)
        {
            rev = (bool)GetTypeValue(vals[3], BasicTypes.Boolean);
        }

        if (vals[0].CanImplicitlyConvert(BasicTypes.Categorical))
        {
            Categorical _1Arg = (Categorical)GetTypeValue(vals[0], BasicTypes.Categorical);
            return new ExpressionInteger(_1Arg.Find(_2Arg, skip, rev));
        }

        if (vals[0].Type != BasicTypes.String)
        {
            throw new Exception("类型不符合：需要String类型。");
        }

        bool ignoreCase = false;
        if (vals.Length == 5)
        {
            ignoreCase = (bool)GetTypeValue(vals[4], BasicTypes.Boolean);
        }

        string strArg = (string)GetTypeValue(vals[0], BasicTypes.String);

        int index;
        if (ignoreCase)
        {
            index = rev
                ? strArg.LastIndexOf(_2Arg, skip, StringComparison.OrdinalIgnoreCase)
                : strArg.IndexOf(_2Arg, skip, StringComparison.OrdinalIgnoreCase);
        }
        else
        {
            index = rev
                ? strArg.LastIndexOf(_2Arg, skip, StringComparison.Ordinal)
                : strArg.IndexOf(_2Arg, skip, StringComparison.Ordinal);
        }

        return new ExpressionInteger(index);
    }

    /// <summary>
    ///     返回字符串或者分类列表的长度。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Len(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Len), 1, 1, vals.Length);

        if (vals[0].Type == 0)
        {
            return new ExpressionInteger(0);
        }

        if (vals[0].CanImplicitlyConvert(BasicTypes.Categorical))
        {
            Categorical cat = (Categorical)GetTypeValue(vals[0], BasicTypes.Categorical);
            return new ExpressionInteger(cat.Count);
        }

        return new ExpressionInteger(((string)GetTypeValue(vals[0], BasicTypes.String)).Length);
    }


    /// <summary>
    ///     从左向右截取指定数目的元素并返回。允许传入Categorical类型或者String类型。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Left(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Left), 2, 2, vals.Length);

        if (vals[0].Type == BasicTypes.Null)
        {
            return new ExpressionNull();
        }

        int count = (int)GetTypeValue(vals[1], BasicTypes.Integer);
        if (vals[0].CanImplicitlyConvert(BasicTypes.Categorical))
        {
            if (count <= 0)
            {
                return new Categorical();
            }

            Categorical cat = (Categorical)GetTypeValue(vals[0], BasicTypes.Categorical);
            if (count >= cat.Count)
            {
                return new Categorical(cat);
            }

            var resCat = new Categorical();
            for (int i = 0; i < count; i++)
            {
                resCat.Add(cat[i]);
            }

            return resCat;
        }

        string str = (string)GetTypeValue(vals[0], BasicTypes.String);

        if (count <= 0)
        {
            return new ExpressionString("");
        }

        if (count < str.Length)
        {
            str = str.Substring(0, count);
        }

        return new ExpressionString(str);
    }

    /// <summary>
    ///     从右向左截取指定数目的元素并返回。允许传入Categorical类型或者String类型。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Right(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Right), 2, 2, vals.Length);

        if (vals[0].Type == BasicTypes.Null)
        {
            return new ExpressionNull();
        }

        int count = (int)GetTypeValue(vals[1], BasicTypes.Integer);
        if (vals[0].CanImplicitlyConvert(BasicTypes.Categorical))
        {
            if (count <= 0)
            {
                return new Categorical();
            }

            Categorical cat = (Categorical)GetTypeValue(vals[0], BasicTypes.Categorical);
            if (count >= cat.Count)
            {
                return new Categorical(cat);
            }

            var resCat = new Categorical();
            for (int i = cat.Count - count; i < cat.Count; i++)
            {
                resCat.Add(cat[i]);
            }

            return resCat;
        }

        string str = (string)GetTypeValue(vals[0], BasicTypes.String);

        if (count <= 0)
        {
            return new ExpressionString("");
        }

        if (count < str.Length)
        {
            str = str.Substring(0, count);
        }

        return new ExpressionString(str);
    }

    /*
     * Mid(Val, Start [, Length])
     *
     * Returns a string containing a number of characters from a position in a string,
     * a category list containing a number of categories from a position in a category list,
     * or an array containing a number of elements from a position in an array.
     *
     * | Parameter | Type   | Remarks
     * |-----------|--------|------------------------------------
     * | Val       | None   | Text value, categorical value, or array to operate on.
     * | Start     | Long   | Position in Val of the first character, category, or element wanted (counting from 0).
     * |           |        | If Start is greater than the number of items in Val, no items are returned.
     * |           |        | If Start is less than 0, items are returned from the start of Val.
     * | Length    | Long   | Optional. Number of characters, categories, or elements to return.
     * |           |        | If Length is omitted, or if there are fewer than Lengthcharacters (including the Start character),
     * |           |        | all characters from Start to the end of the string are returned.
     * |           |        | If Start + Length is < 1, no items are returned.
     * | (return)  | None   | The required characters, categories, or elements from Val.
     *
     * Remarks
     *
     * For type Text, the return value is of type Text, and contains Length characters from the position Start in Val.
     * For type Categorical, the value is of type Categorical, and contains Length categories from the position Start in Val.
     * For an array (which can contain values of any type), the return value is an array, and contains Length elements from the position Start in Val.
     * For any other type, an error occurs.
     *
     * When Val is NULL, the return value is NULL.
     *
     *
     */

    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Mid(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Mid), 2, 3, vals.Length);

        if (vals[0].Type == BasicTypes.Null)
        {
            return new ExpressionNull();
        }

        int start = (int)GetTypeValue(vals[1], BasicTypes.Integer);
        int length;

        if (vals[0].CanImplicitlyConvert(BasicTypes.Categorical))
        {
            Categorical cat = (Categorical)GetTypeValue(vals[0], BasicTypes.Categorical);
            length = cat.Count - start;
            if (vals.Length == 3)
            {
                length = (int)GetTypeValue(vals[2], BasicTypes.Integer);
            }

            var resCat = new Categorical();

            if (start > cat.Count)
            {
                return resCat;
            }

            while (length > 0)
            {
                resCat.Add(cat[start]);
                start++;
                length--;
            }

            return resCat;
        }

        string str = (string)GetTypeValue(vals[0], BasicTypes.String);

        length = str.Length - start;
        if (vals.Length == 3)
        {
            length = (int)GetTypeValue(vals[2], BasicTypes.Integer);
        }

        if (start + length >= str.Length)
        {
            str = str.Substring(start);
        }
        else
        {
            str = str.Substring(start, length);
        }

        return new ExpressionString(str);
    }

    #endregion

    #region Conversion Functions

    /// <summary>
    ///     将指定值转换成布尔值类型。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType CBoolean(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(CBoolean), 1, 1, vals.Length);
        return vals[0].ConvertTo(BasicTypes.Boolean);
    }

    /// <summary>
    ///     将指定值转换成分类值类型。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType CCategorical(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(CCategorical), 1, 1, vals.Length);
        return vals[0].ConvertTo(BasicTypes.Categorical);
    }

    /// <summary>
    ///     将指定值转换成整数类型。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType CLong(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(CLong), 1, 1, vals.Length);
        return vals[0].ConvertTo(BasicTypes.Integer);
    }

    /// <summary>
    ///     将指定值转换成小数类型。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType CDouble(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(CDouble), 1, 1, vals.Length);
        return vals[0].ConvertTo(BasicTypes.Double);
    }

    #endregion

    #region Mathematical Functions

    /// <summary>
    ///     返回数字的绝对值。返回结果是浮点数。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Abs(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Abs), 1, 1, vals.Length);
        return new ExpressionDouble(Math.Abs((double)GetTypeValue(vals[0], BasicTypes.Double)));
    }

    /// <summary>
    ///     返回数字的反正切值。返回结果是浮点数。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Atn(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Atn), 1, 1, vals.Length);
        return new ExpressionDouble(Math.Atan((double)GetTypeValue(vals[0], BasicTypes.Double)));
    }


    /// <summary>
    ///     返回数字的余弦值。返回结果是浮点数。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Cos(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Cos), 1, 1, vals.Length);
        return new ExpressionDouble(Math.Cos((double)GetTypeValue(vals[0], BasicTypes.Double)));
    }


    /// <summary>
    ///     返回数字的正弦值。返回结果是浮点数。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Sin(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Sin), 1, 1, vals.Length);
        return new ExpressionDouble(Math.Sin((double)GetTypeValue(vals[0], BasicTypes.Double)));
    }

    /// <summary>
    ///     返回数字的正切值。返回结果是浮点数。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Tan(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Tan), 1, 1, vals.Length);
        return new ExpressionDouble(Math.Tan((double)GetTypeValue(vals[0], BasicTypes.Double)));
    }


    /// <summary>
    ///     返回数字的e^n值。返回结果是浮点数。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Exp(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Exp), 1, 1, vals.Length);
        return new ExpressionDouble(Math.Exp((double)GetTypeValue(vals[0], BasicTypes.Double)));
    }

    /// <summary>
    ///     获取小数中的整数部分。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Int(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Int), 1, 1, vals.Length);
        return new ExpressionInteger((int)Math.Floor((double)GetTypeValue(vals[0], BasicTypes.Double)));
    }

    /// <summary>
    ///     计算给定数字的对数。默认底数是e。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Log(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Log), 1, 1, vals.Length);
        double bs = Math.E;
        if (vals.Length == 2)
        {
            bs = (double)GetTypeValue(vals[1], BasicTypes.Double);
        }

        if (bs <= 0)
        {
            bs = Math.E;
        }

        return new ExpressionDouble(Math.Log((double)GetTypeValue(vals[0], BasicTypes.Double), bs));
    }

    /// <summary>
    ///     返回一系列数字中的最大值。至少有一个数字。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType MaxOf(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(MaxOf), 1, 0, vals.Length);

        double max = double.NaN;
        foreach (ExpressionBasicType val in vals)
        {
            if (val.Type == BasicTypes.Null)
            {
                continue;
            }

            double dbVal = (double)GetTypeValue(val, BasicTypes.Double);
            if (double.IsNaN(max) || dbVal > max)
            {
                max = dbVal;
            }
        }

        if (double.IsNaN(max))
        {
            return new ExpressionNull();
        }

        return new ExpressionDouble(max);
    }


    /// <summary>
    ///     返回一系列数字中的最小值。至少有一个数字。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType MinOf(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(MinOf), 1, 0, vals.Length);

        double min = double.NaN;
        foreach (ExpressionBasicType val in vals)
        {
            double dVal;

            if (val.Type == BasicTypes.Null)
            {
                dVal = 0;
            }
            else
            {
                dVal = (double)GetTypeValue(val, BasicTypes.Double);
            }

            if (double.IsNaN(min) || dVal < min)
            {
                min = dVal;
            }
        }

        if (double.IsNaN(min))
        {
            return new ExpressionNull();
        }

        return new ExpressionDouble(min);
    }

    /*
     *
     *  Pow(Val1, Val2)
     *
     *  Remarks
     *      The return value is Val1 raised to the power of Val2.
     *      If Val1 is 0.0, the return value is 0.0.
     *      If the current data value is NULL, Val1 is 0.0 and the return value is 0.0.
     *      If Val1 is < 0, an error occurs if Val2 is not an integer value.
     *
     *      When Val1 or Val2 are large numbers, the return value can have more digits than can be accurately represented by
     *      the Double data type. However, the function does not check for this and does not issue an error when this happens.
     *
     */

    /// <summary>
    ///     计算一个数字的n次方数值。第一个参数是底数，第二个参数是指数值。
    /// </summary>
    /// <param name="vals"></param>
    /// <returns></returns>
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Pow(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Pow), 2, 2, vals.Length);
        double val1 = (double)GetTypeValue(vals[0], BasicTypes.Double);
        double val2 = (double)GetTypeValue(vals[1], BasicTypes.Double);
        return new ExpressionDouble(Math.Pow(val1, val2));
    }

    /**
     * Round(Val [, Digits [, Policy]])
     *
     *
     * Policy can also be set to any combination of the values in the following table. To combine values, add them together:
     *
     * 1 - Round Val to a number of significant digits rather than to a number of decimal places.
     * 2 - If Val is exactly halfway between the two nearest values of the required precision, round to the higher value rather than rounding to even.
     * However, if value 4 below is also set, round to the lower value of the two nearest values.
     * 4 - If Val is exactly halfway between the two nearest values of the required precision, round to odd rather than rounding to even.
     * However, if value 2 above is also set, round to the lower of the two nearest values.
     * 8 - If Val is negative and exactly halfway between the two nearest values of the required precision, round the absolute value and make its sign negative.
     * If this value is set, "higher" and "lower" in values 2 and 4 above means "having a larger absolute value" and "having a smaller absolute value" respectively.
     * This value has no effect if value 2 is not set.
     */
    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Round(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Round), 1, 3, vals.Length);
        double _1Arg = (double)GetTypeValue(vals[0], BasicTypes.Double);
        MidpointRounding roundPolicy = MidpointRounding.ToEven;

        if (vals.Length >= 2)
        {
            int decimals = (int)GetTypeValue(vals[1], BasicTypes.Integer);

            if (vals.Length == 3)
            {
                int policy = (int)GetTypeValue(vals[2], BasicTypes.Integer);
                double res = _1Arg;

                if ((policy & 0x2) != 0)
                {
                    roundPolicy = MidpointRounding.AwayFromZero;
#if NET8_0_OR_GREATER
                    if ((policy & 0x8) != 0)
                    {
                        // 如果设置了 0x4，取较小绝对值的值。
                        if ((policy & 0x4) != 0)
                        {
                            roundPolicy = MidpointRounding.ToZero;
                        }
                        // 取较大绝对值的值
                        else
                        {
                            roundPolicy = _1Arg > 0
                                ? MidpointRounding.ToPositiveInfinity
                                : MidpointRounding.ToNegativeInfinity;
                        }
                    }
                    // 如果设置了 0x4，取较小值。
                    else if ((policy & 0x4) != 0)
                    {
                        roundPolicy = MidpointRounding.ToNegativeInfinity;
                    }
#endif
                }
                // 舍入到奇数
                else if ((policy & 0x4) != 0)
                {
                    double rounded = Math.Round(res);

                    if (rounded % 2 == 0)
                    {
                        res = rounded > res ? rounded - 1 : rounded + 1;
                    }
                }

                // 保留有效位数
                if ((policy & 0x1) != 0)
                {
                    // 计算当前res的有效整数位数
                    int pow = 1;
                    while ((int)res / (int)Math.Pow(10, pow) != 0)
                    {
                        pow++;
                    }

                    // 如果有效位数大于整数位数，检查小数位数
                    if (pow < decimals)
                    {
                        res = Math.Round(res, decimals - pow, roundPolicy);
                    }
                    else
                    {
                        int decimalPlace = (int)Math.Pow(10, pow - decimals);
                        res = (int)res / decimalPlace * decimalPlace;
                    }

                    return new ExpressionDouble(res);
                }
            }

            return new ExpressionDouble(Math.Round(_1Arg, decimals, roundPolicy));
        }

        return new ExpressionDouble(Math.Round(_1Arg, roundPolicy));
    }


    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Sgn(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Sgn), 1, 1, vals.Length);
        double _1Arg = (double)GetTypeValue(vals[0], BasicTypes.Double);
        return new ExpressionInteger(Math.Sign(_1Arg));
    }


    [ExpressionBuiltInFunction]
    public static ExpressionBasicType Sqrt(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(Sqrt), 1, 1, vals.Length);
        double _1Arg = (double)GetTypeValue(vals[0], BasicTypes.Double);
        return new ExpressionDouble(Math.Sqrt(_1Arg));
    }

    #endregion

    #region Miscellaneous Functions

    // BitAnd(Val1 [, Vals, ...])

    [ExpressionBuiltInFunction]
    public static ExpressionBasicType BitAnd(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(BitAnd), 1, 0, vals.Length);
        int _1Arg = (int)GetTypeValue(vals[0], BasicTypes.Integer);
        int res = _1Arg;

        for (int i = 1; i < vals.Length; i++)
        {
            res &= (int)GetTypeValue(vals[i], BasicTypes.Integer);
        }

        return new ExpressionInteger(res);
    }

    [ExpressionBuiltInFunction]
    public static ExpressionBasicType BitNot(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(BitNot), 1, 1, vals.Length);
        int _1Arg = (int)GetTypeValue(vals[0], BasicTypes.Integer);
        return new ExpressionInteger(~_1Arg);
    }

    [ExpressionBuiltInFunction]
    public static ExpressionBasicType BitOr(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(BitOr), 1, 0, vals.Length);
        int _1Arg = (int)GetTypeValue(vals[0], BasicTypes.Integer);
        int res = _1Arg;

        for (int i = 1; i < vals.Length; i++)
        {
            res |= (int)GetTypeValue(vals[i], BasicTypes.Integer);
        }

        return new ExpressionInteger(res);
    }

    [ExpressionBuiltInFunction]
    public static ExpressionBasicType BitXor(params ExpressionBasicType[] vals)
    {
        CheckArgumentNumbers(nameof(BitXor), 1, 0, vals.Length);
        int _1Arg = (int)GetTypeValue(vals[0], BasicTypes.Integer);
        int res = _1Arg;

        for (int i = 1; i < vals.Length; i++)
        {
            res ^= (int)GetTypeValue(vals[i], BasicTypes.Integer);
        }

        return new ExpressionInteger(res);
    }

    #endregion
}